home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume7 / bpatch < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  47.8 KB

  1. Subject:  v07i014:  Binary (file) patcher/viewer
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: pyramid!lukeII!itkin (Steven List)
  6. Mod.sources: Volume 7, Issue 14
  7. Archive-name: bpatch
  8.  
  9.  
  10.  
  11. [  See me notes at the end of the README.  --r$  ]
  12.  
  13. #!/bin/sh
  14. # This is a shell archive.  Remove anything before this line,
  15. # then unpack it by saving it in a file and typing "sh file".
  16.  
  17. # Exit status; set to 1 on "wc" errors or if would overwrite.
  18. STATUS=0
  19. # Contents:  README Makefile bpatch.1 bpatch.c
  20.  
  21. echo x - README
  22. if test -f README ; then
  23.     echo README exists, putting output in $$README
  24.     OUT=$$README
  25.     STATUS=1
  26. else
  27.     OUT=README
  28. fi
  29. sed 's/^XX//' > $OUT <<'@//E*O*F README//'
  30. XXHerewith find BPATCH - a marvelously utile utility.  While not of
  31. XXmy original creation, I have been given permission to place in the
  32. XXpublic domain.  I have made substantial modifications to the original
  33. XXsource given to me.  Specifically I cleaned it up a bit and made it
  34. XXwork with SVR2 curses.  Personally, I think it's pretty neat.
  35.  
  36. XXOK - for those of you who may scream by now "WHAT THE HELL IS IT ALREADY?"
  37. XXI respond that it is a binary file editor and dump utility!  That's 
  38. XXright!  You can dump your file in the nicely laid out side-by-side
  39. XXhex and ascii format or you can actually EDIT it at your terminal!
  40. XXYes, I have seen the BED editor that came across the network.
  41. XXUnfortunately, it converted the entire file before and after editing.
  42. XXBpatch, on the other hand, works with one 256 byte page at a time.
  43. XXIt is marvelously useful for looking at things like raw disk UNIFY
  44. XXdatabases and even raw disks!  While the man page may not be absolutely
  45. XXup to date, the online help is.  Try the question mark (?) command.
  46.  
  47. XXAs always, I would love to hear about bugs/changes/enhancements/requests.
  48. XX    Steven List @ Benetics Corporation, Mt. View, CA
  49. XX    Just part of the stock at "Uncle Bene's Farm"
  50. XX    {cdp,engfocus,idi,oliveb,opusys,plx,pyramid,tolerant}!bene!luke!itkin
  51.  
  52. XXAddition by the moderator:
  53. XXI have added code, surrounded by #ifdef MOD_HAX, that gets bpatch
  54. XX(barely?) working on my 4.2 system.  I would be very interested in
  55. XXpublishing a set of diffs that's less of a hack.  Oh yeah:  I also
  56. XXwrote the Makefile.
  57. XX    /Rich $alz
  58. @//E*O*F README//
  59. chmod u=rw,g=rw,o=rw $OUT
  60.  
  61. echo x - Makefile
  62. if test -f Makefile ; then
  63.     echo Makefile exists, putting output in $$Makefile
  64.     OUT=$$Makefile
  65.     STATUS=1
  66. else
  67.     OUT=Makefile
  68. fi
  69. sed 's/^XX//' > $OUT <<'@//E*O*F Makefile//'
  70. XX# This may have to change on your system.
  71. XX# You may have to fiddle with various combinations of curses, termcap,
  72. XX# terminfo, etc.  Good luck!
  73. XXLIBS    = -lcurses -ltermcap
  74. XX#LIBS    = -ltermlib
  75. XX#LIBS    = -lterminfo
  76.  
  77. XX# However you need getopt.
  78. XXGETOPT    = -lgetopt
  79.  
  80. XX# If you're running on a 4.[23] system, you probably want this.
  81. XXWORK    = -DMOD_HAX
  82.  
  83. XXCFLAGS    = -O $(WORK)
  84.  
  85. XXbpatch:        bpatch.o
  86. XX    $(CC) -o bpatch $(CFLAGS) bpatch.o $(GETOPT) $(LIBS)
  87.  
  88. XXinstall:
  89. XX    @echo Use cp to put things where you want them
  90. @//E*O*F Makefile//
  91. chmod u=rw,g=rw,o=rw $OUT
  92.  
  93. echo x - bpatch.1
  94. if test -f bpatch.1 ; then
  95.     echo bpatch.1 exists, putting output in $$bpatch.1
  96.     OUT=$$bpatch.1
  97.     STATUS=1
  98. else
  99.     OUT=bpatch.1
  100. fi
  101. sed 's/^XX//' > $OUT <<'@//E*O*F bpatch.1//'
  102. XX.TH "bpatch" "1" "Benetics Local"
  103. XX.if t .nr LL 7i
  104. XX.if t .nr IN .8i
  105. XX.if n .nr LL 70
  106. XX.if n .nr IN 8
  107. XX.fi
  108. XX.ad b
  109. XX.SH NAME
  110. XXbpatch - binary patch and dump file utility
  111. XX.SH SYNOPSIS
  112. XXbpatch [ -b blksize ] [ -d ] [ -D pagecnt ] [ -e ] [ -p ] [ -r reclen ] [ -s ] [ -x ] file...
  113. XX.SH DESCRIPTION
  114. XX\fIBpatch\fR allows the viewing and/or modification of files, independent of
  115. XXfile type (text, executable, data file, and so forth).  \fIBpatch\fR
  116. XXallows the data to either be examined at the terminal, dumped to a print
  117. XXdevice or file, or edited in the general manner of \fIvi(1)\fR.  The
  118. XXdata in the file is dumped or displayed in \fIpages\fR of 256 bytes.
  119. XX.SS Options
  120. XX.IP "-b blksize" 12
  121. XXThe \fI-b\fR option specifies the blocksize of the data file.  This is used
  122. XXprimarily with tapes, and is allowed only with one of the dump (\fI-d\fR
  123. XXor \fI-D\fR) options.  When this option is specified, the file is opened
  124. XXin readonly mode.
  125. XX.IP "-d" 12
  126. XXThe \fI-d\fR option indicates that a dump (no terminal manipulation) is
  127. XXto be performed.  The entire file will be dumped to standard output.  No
  128. XXediting of the data is allowed and the file is opened in readonly mode.
  129. XX.IP "-D pagecnt" 12
  130. XXThe \fI-D\fR option is similar to the \fI-d\fR option, with the
  131. XXfollowing exception: the pagecnt argument limits the dump to the
  132. XXspecified number of \fIpages\fR.
  133. XX.IP "-e" 12
  134. XXThe \fI-e\fR option indicates that the file contains EBCDIC data and
  135. XXshould be converted in the character portion of the dump.
  136. XX.IP "-p" 12
  137. XXUsed with one of the \fIdump\fR options, this option causes the program
  138. XXto pause between \fIpages\fR.  The program will then wait for the user
  139. XXto press either the \fIreturn\fR key to continue, or the \fIDEL\fR (or
  140. XX\fIrubout\fR) key to stop the dump.
  141. XX.IP "-r reclen" 12
  142. XXThe \fI-r\fR option indicates the record length of the data within the
  143. XXdump.  When specified, this option causes \fIbpatch\fR to place a colon
  144. XX(:) between the last byte of one record and the first byte of the next.
  145. XX.IP "-s" 12
  146. XXThis option turns on the byte swap option.  It may be toggled dynamically
  147. XXduring execution (see \fI-x\fP under Commands below).
  148. XX.IP "-x" 12
  149. XXThis option specifies the suppression of pages that contain only NUL
  150. XXcharacters.  The result is that only the page header (name and page
  151. XXnumber) will appear for such a page.  This option may only be used with
  152. XXone of the dump options.
  153. XX.SS Arguments
  154. XX.IP file 12
  155. XXAny number of files may be specified.
  156. XX.SS Commands
  157. XXAll commands are valid only in the non-dump, interactive mode.  Commands
  158. XXmay be entered in either upper or lower case.  Commands of the form '^x'
  159. XXindicate that the control character \fIx\fR is to be entered.
  160. XX.P
  161. XXAll commands that request movement within a file or between files cannot
  162. XXbe executed if any changes have been made.  To proceed in this case, the
  163. XXuser must either enter the \fIw\fR command, the \fIu\fR command, or the
  164. XX\fIr\fR command.
  165. XX.P
  166. XXRequesting a next or previous file when there is no such will cause the
  167. XXissuance of an error message.
  168. XX.P
  169. XXNote that certain commands allow/require either some text or numeric
  170. XXvalue.  In those cases, the user should type in characters and end the
  171. XXstring with either a <cr> or <DEL>.
  172. XX.IP ? 6
  173. XXDisplay the help screen.  The help screen will remain until the user
  174. XXeither redraws the screen (see \fI^r\fR) or changes pages or files.
  175. XX.IP ! 6
  176. XXExecute the following command in the shell.
  177. XX.IP backslash 6
  178. XXDisplay the previous page.
  179. XX.IP <cr> 6
  180. XXDisplay the next page.
  181. XX.IP DEL 6
  182. XXQuit the program if no changes have been made.
  183. XX.IP / 6
  184. XXThis command initiates an ASCII search.  The text entered on the command
  185. XXline will be used as a search string, and the file will be searched
  186. XXstarting with the current page.  When the string is found, the page
  187. XXcontaining the string will be displayed.  If the string is not found, an
  188. XXapapropriate message will be displayed.
  189. XX.IP ^f 6
  190. XXOpen a named file whose name will be entered on the command line and
  191. XXfollowed either by <cr> or DEL.
  192. XX.IP ^n 6
  193. XXOpen the next file and display the first page.
  194. XX.IP ^p 6
  195. XXOpen the previous file and display the first page.
  196. XX.IP ^q 6
  197. XXQuit without writing current changes.
  198. XX.IP ^r 6
  199. XXRedraw the screen.
  200. XX.IP NNN 6
  201. XXEntering a numeric value requests that the specified page be displayed.
  202. XX.IP -x 6
  203. XXToggle the command line option represented by \fIx\fR:
  204. XX.RS 12
  205. XX.IP a 6
  206. XXToggle display to ascii (assume data is ascii).
  207. XX.IP e 6
  208. XXToggle display to dbcdic (assume data is ebcdic).
  209. XX.IP s 6
  210. XXToggle byte swap.
  211. XX.RE
  212. XX.IP a 6
  213. XXEdit the ASCII display.  End edits by pressing the DEL key.  All other
  214. XXcharacters will be treated as valid input.  Cursor movement keys (arrows
  215. XXand home) allow movement within the edit window.  Nonprinting
  216. XXcharacters are displayed as dot (.) in this window.
  217. XX.IP f 6
  218. XXDisplay the first page in the current file.
  219. XX.IP g 6
  220. XXDisplay the page containing the byte address typed in following the command.
  221. XX.IP h 6
  222. XXEdit the HEXADECIMAL display.  End edits by pressing DEL key.  Cursor
  223. XXmovement keys (arrows and home) allow movement within the edit window.
  224. XXTwo keystrokes are required to modify a byte, and both must be valid
  225. XXhexadecimal values (0-9 and a-f).  To cancel a change after typing one
  226. XXcharacter, press DEL.
  227. XX.IP l 6
  228. XXDisplay the last page in the current file.
  229. XX.IP q 6
  230. XXQuit the file.  A warning will be issued if any changes have been made
  231. XXbut not written out.
  232. XX.IP r 6
  233. XXReread the current page.
  234. XX.IP u 6
  235. XXUndo all changes to the current page.
  236. XX.IP w 6
  237. XXWrite out the current page.
  238. XX.SH "SEE ALSO"
  239. XXod(1)
  240. @//E*O*F bpatch.1//
  241. chmod u=rw,g=rw,o=rw $OUT
  242.  
  243. echo x - bpatch.c
  244. if test -f bpatch.c ; then
  245.     echo bpatch.c exists, putting output in $$bpatch.c
  246.     OUT=$$bpatch.c
  247.     STATUS=1
  248. else
  249.     OUT=bpatch.c
  250. fi
  251. sed 's/^XX//' > $OUT <<'@//E*O*F bpatch.c//'
  252. XX/*T bpatch - A binary file patch/dump utility */
  253. XX/*S Introduction */
  254. XX/*F bpatch ***********************************************************
  255. XX* bpatch
  256. XX* by Garry M Johnson - 09/17/84
  257. XX* (C) Copyright 1984, 1985
  258. XX*
  259. XX* Change History:
  260. XX*  03/05/86 - added further terminal independence
  261. XX*             added use of ioctl (see main and mstdin)
  262. XX*             added -D versus -d command line option
  263. XX*             added use of standard getopt
  264. XX*             cleaned up code, eliminated function "ikf"
  265. XX*             added original versions of ezlib functions, such as
  266. XX*               icc, setterm, cm, mstdin, erase, length, move
  267. XX*             added ^R, ^Q, ^N, and ^P commands
  268. XX*             added ^F, !, and ^X (-X) commands
  269. XX*              changed name to "bpatch"
  270. XX*              added direct address command (g)
  271. XX*             added ASCII search capability
  272. XX*  07/07/86 - converted to use curses
  273. XX*             modified direct addressing to use suffixes
  274. XX*             updated HELP function
  275. XX*
  276. XX*   Steven List @ Benetics Corporation, Mt. View, CA
  277. XX*   {cdp,engfocus,idi,oliveb,plx,tolerant}!bene!luke!itkin
  278. XX*********************************************************************/
  279. XX/*E*/
  280. XX/*S includes, globals, and defines */
  281. XX/*Page Eject*/
  282. XX#include    <curses.h>
  283. XX#include <fcntl.h>
  284. XX#include <signal.h>
  285. XX#include <ctype.h>
  286. XX#include <sys/types.h>
  287. XX#include <sys/stat.h>
  288.  
  289. XXstatic int pbrk = 0;
  290. XXstruct stat sb;
  291.  
  292. XXvoid icc ();
  293. XXvoid copyrec ();
  294. XXvoid schwapp ();
  295.  
  296. XX    /* ------------------------------------------------------------ */
  297. XX    /* Some defines added by the moderator to get it work on 4.2    */
  298. XX    /* ------------------------------------------------------------ */
  299. XX#ifdef    MOD_HAX
  300. XX    /* Fifos?  We ain't got no steenkin' fifos. */
  301. XX#define S_IFIFO        123450
  302. XX    /* "Spelling differences." */
  303. XX#define beep()        fprintf (stderr, "\007")
  304. XX#define cbreak()    crmode()
  305. XX    /* Our curses doesn't translate keypad keys to single characters. */
  306. XX#define keypad(a, b)    /* null */
  307. XX#define KEY_UP        '^'
  308. XX#define KEY_DOWN    'v'
  309. XX#define KEY_LEFT    '<'
  310. XX#define KEY_RIGHT    '>'
  311. XX#define KEY_HOME    '@'
  312. XX#endif    /* MOD_HAX */
  313.  
  314.  
  315. XX    /* ------------------------------------------------------------ */
  316. XX    /* Some convenient defines                                      */
  317. XX    /* ------------------------------------------------------------ */
  318.  
  319. XX#define DEL '\177'
  320. XX#define HEX 1
  321. XX#define ALPHA 0
  322.  
  323. XX    /* ------------------------------------------------------------ */
  324. XX    /* general purpose identification and control variables         */
  325. XX    /* ------------------------------------------------------------ */
  326.  
  327. XXchar    filename[64];            /* current file being examined        */
  328. XXchar    record[16][16];            /* record (page) buffer                */
  329. XXchar    unch_rec[16][16];        /* record before any changes        */
  330. XXint     zp;                        /* current input character            */
  331.  
  332. XXint        block = 0;                /* block size if -b in command        */
  333. XXint        block_spec;                /* true if file is block special    */
  334. XXint        bytes = 0;                /* number of bytes from last read    */
  335. XXint        char_spec;                /* true if file is char special        */
  336. XXint        debug = 0;                /* true if debug is turned on        */
  337. XXint        dir_spec;                /* true if file is directory        */
  338. XXint        dump = 0;                /* nonzero if dump instead of change*/
  339. XXint        ebcdic = 0;                /* true if -e option                */
  340. XXint        fifo_spec;                /* true if file is fifo                */
  341. XXint        honly = 0;                /* true if dump is to be hex only    */
  342. XXint        mod = 0;                /* true if record has been modified    */
  343. XXint        pause = 0;                /* true if -p option                */
  344. XXint        rawfile = 0;            /* true if file is c/b/p            */
  345. XXint        reclen = 0;                /* record length, if -r                */
  346. XXint        recno = 0;                /* current record (page) number        */
  347. XXint        stay = 0;                /* true if no position change         */
  348. XXint        swab = 0;                /* true if byte swapping is on        */
  349. XXint        windowed = 0;            /* true if windowing - not dump        */
  350.  
  351. XXlong    position = 0;            /* byte address in file                */
  352.  
  353. XXWINDOW *hexwin = NULL;
  354. XXWINDOW *alphawin = NULL;
  355. XXWINDOW *errwin = NULL;
  356.  
  357. XX/*S main - control all the work from here */
  358. XX/*H main *************************************************************
  359. XX*
  360. XX*                            main
  361. XX*
  362. XX*    set up the globals, initilize the state, and process the file
  363. XX*
  364. XX*********************************************************************/
  365. XX/*E*/
  366. XXmain (argc, argv)
  367. XXint argc;
  368. XXchar *argv[];
  369. XX{
  370. XX    extern WINDOW *subwin ();
  371. XX    extern WINDOW *newwin ();
  372.  
  373. XX#ifdef    MOD_HAX
  374. XX#else    /* use original code... */
  375. XX    struct termio asis;
  376. XX#endif    /* MOD_HAX */
  377.  
  378. XX    register char    *cp;                /* general purpose char ptr    */
  379. XX    extern   char    *gets ();            /* get string from stdin    */
  380. XX             char    m = '\017';            /* mask for hex edit        */
  381. XX             char    response[512];        /* general purpose buffer    */
  382. XX             int     z;                    /* character read in        */
  383. XX         
  384. XX    int        breakp ();            /* signal trapping function            */
  385. XX    int        c;                    /* current screen column            */
  386. XX    int        change = 0;            /* true if cmd line option toggled    */
  387. XX    int        fid;                /* file descriptor                    */
  388. XX    int        firstfile;            /* arg # of first file in cmd line    */
  389. XX    int        h;                    /* temp for hex edit                */
  390. XX    int        i;                    /* general purpose loop index        */
  391. XX    int        j;                    /* general purpose loop index        */
  392. XX    int        r;                    /* current screen row                */
  393. XX    int        hexc;                /* current cursor column in hexwin    */
  394.  
  395. XX    long    byteaddr;            /* planned byte address for 'G'        */
  396. XX    long    size;                /* file size in bytes                */
  397. XX    long    status;                /* EOF if at end of file or error    */
  398.  
  399. XX    extern int optind;            /* getopt index into argv            */
  400. XX    extern char *optarg;        /* getopt pointer to opt arg        */
  401.  
  402. XX    extern long getnum ();
  403. XX    extern char *instr ();        /* get a string from the cmd line    */
  404. XX    extern int reset ();        /* exit function - reset terminal    */
  405.  
  406. XX    /* ------------------------------------------------------------ */
  407. XX    /* set up signal handling                                       */
  408. XX    /* ------------------------------------------------------------ */
  409.  
  410. XX    if (!dump) signal (SIGINT, breakp);
  411.  
  412. XX    signal (SIGTERM, reset);
  413.  
  414. XX    /* ------------------------------------------------------------ */
  415. XX    /* process command line arguments                               */
  416. XX    /* ------------------------------------------------------------ */
  417.  
  418. XX    while ((i = getopt (argc, argv, "r:dD:b:pxXse")) != EOF)
  419. XX    {
  420. XX        switch (i)
  421. XX        {
  422. XX            case    'b':        /* blocking                    */
  423. XX                block = atoi (optarg);
  424. XX                if (block < 1 || block > 10240)
  425. XX                {
  426. XX                    fprintf (stderr,
  427. XX                        "invalid block size: %d\n", block);
  428. XX                    exit (1);
  429. XX                }
  430. XX                break;
  431. XX            case    'd':        /* straight dump - no limit    */
  432. XX                dump = -1;
  433. XX                break;
  434. XX            case    'D':        /* dump - page count spec    */
  435. XX                dump = atoi (optarg);
  436. XX                break;
  437. XX            case    'e':        /* file is ebcdic            */
  438. XX                ebcdic = 1;
  439. XX                break;
  440. XX            case    'p':        /* pause between pages - dump    */
  441. XX                pause = 1;
  442. XX                break;
  443. XX            case    'r':        /* record length for dump        */
  444. XX                reclen = atoi (optarg);
  445. XX                break;
  446. XX            case    's':        /* byte swapping required        */
  447. XX                swab = 1;
  448. XX                break;
  449. XX            case    'x':        /* hex dump only                */
  450. XX                honly = 1;
  451. XX                break;
  452. XX            case    'X':
  453. XX                debug = 1;
  454. XX                break;
  455. XX            default:            /* uhoh                            */
  456. XX                fprintf (stderr,
  457. XX"usage: bpatch [ -b blocksz ] [ -d<ump> ] [ -D pagecnt ] [ -e<bcdic> ]\n");
  458. XX                fprintf (stderr,
  459. XX"              [ -p<ause> ] [ -r reclen ] [ -s<wap bytes> ] [ -x<only> ]\n");
  460. XX                exit (1);
  461. XX        }
  462. XX    }
  463.  
  464. XX    /* ------------------------------------------------------------ */
  465. XX    /* check for valid combinations of options                      */
  466. XX    /* ------------------------------------------------------------ */
  467.  
  468. XX    if ((honly || block || reclen || pause ) && !dump)
  469. XX    {
  470. XX        fprintf (stderr, "-x|-b|-r|-p requires -d or -D\n");
  471. XX        exit (2);
  472. XX    }
  473.  
  474. XX    /* ------------------------------------------------------------ */
  475. XX    /* At least one file name must be specified on the cmd line     */
  476. XX    /* ------------------------------------------------------------ */
  477.  
  478. XX    if (optind == argc)
  479. XX    {
  480. XX        fprintf (stderr, "no file name(s) specified\n");
  481. XX        exit (2);
  482. XX    }
  483.  
  484. XX    /* ------------------------------------------------------------ */
  485. XX    /* set up the screen, if this is an interactive session         */
  486. XX    /* ------------------------------------------------------------ */
  487.  
  488. XX    if (!dump)
  489. XX    {
  490. XX        windowed = 1;
  491. XX        initscr ();
  492. XX        nonl ();
  493. XX        noecho ();
  494. XX        cbreak ();
  495. XX        keypad (stdscr, TRUE);
  496. XX        hexwin = subwin (stdscr, 16, 48, 4, 4);
  497. XX        keypad (hexwin, TRUE);
  498. XX        alphawin = subwin (stdscr, 16, 16, 4, 57);
  499. XX        keypad (alphawin, TRUE);
  500. XX        errwin = subwin (stdscr, 1, 80, 23, 0);
  501.  
  502. XX#ifdef    MOD_HAX
  503. XX        /* This is not exactly what the original code does,
  504. XX           but it's good enough.  -r$ */
  505. XX        raw();
  506. XX#else    /* use original code... */
  507. XX        ioctl (0, TCGETA, &asis);
  508. XX        asis.c_cc[VINTR] = '\0';
  509. XX        asis.c_iflag &= ~IXON;
  510. XX        asis.c_iflag &= ~IXOFF;
  511. XX        asis.c_iflag &= ~IXANY;
  512. XX        ioctl (0, TCSETA, &asis);
  513. XX#endif    /* MOD_HAX */
  514. XX    }
  515.  
  516. XX    /* ------------------------------------------------------------ */
  517. XX    /* save the first file's index for backing up later             */
  518. XX    /* ------------------------------------------------------------ */
  519.  
  520. XX    firstfile = optind;
  521.  
  522. XX    /* ------------------------------------------------------------ */
  523. XX    /* open the first file                                          */
  524. XX    /* ------------------------------------------------------------ */
  525.  
  526. XX    for (fid = -1; fid < 0 && optind < argc;)
  527. XX    {
  528. XX        fid = ckfile (argv[optind], &size);
  529. XX        if (fid < 0) optind++;
  530. XX    }
  531. XX    if (fid < 0)
  532. XX    {
  533. XX        fprintf (stderr, "could not handle the file list\n");
  534. XX        exit (2);
  535. XX    }
  536.  
  537. XX    strncpy (filename, argv[optind], sizeof filename);
  538.  
  539. XX    if (block != 0)
  540. XX    {
  541. XX        size = -1;
  542. XX    }
  543.  
  544. XX    recno = 0;
  545. XX    stay = 0;
  546. XX    mod = 0;
  547. XX    status = 0;
  548.  
  549. XX    /* ------------------------------------------------------------ */
  550. XX    /* Until the user exits...                                      */
  551. XX    /* ------------------------------------------------------------ */
  552.  
  553. XX    if (!dump) clear ();
  554.  
  555. XX    while (status != EOF)
  556. XX    {
  557. XX    /* ------------------------------------------------------------ */
  558. XX    /* change of location - read and display                        */
  559. XX    /* ------------------------------------------------------------ */
  560. XX        if (stay == 0)
  561. XX        {
  562. XX            position = lseek (fid, (long)(recno * 256), 0);
  563.  
  564. XX            if ((bytes = bread (fid, record, 256, block)) < 0)
  565. XX            {
  566. XX                errmsg ("error on reading file %s", filename);
  567. XX                status = EOF;
  568. XX                continue;
  569. XX            }
  570. XX            if (bytes > 0)
  571. XX            {
  572. XX                if (swab) schwapp (record, 256);
  573.  
  574. XX                copyrec (record, unch_rec, sizeof record);
  575.  
  576. XX                show (bytes, record, filename, size, recno,
  577. XX                        position, m,reclen, dump, ebcdic, swab,
  578. XX                        block, honly);
  579. XX            }
  580. XX            mod = 0;
  581. XX        }
  582. XX    /* ------------------------------------------------------------ */
  583. XX    /* not interactive - keep dumping or open next file             */
  584. XX    /* ------------------------------------------------------------ */
  585. XX        if (dump)
  586. XX        {
  587. XX            if ((dump < 0 && bytes == 0) || (--dump == 0))
  588. XX            {
  589. XX                if (optind == argc) status = EOF;
  590. XX                else
  591. XX                {
  592. XX                    close (fid);
  593. XX                    fid = -1;
  594. XX                    for (optind++; fid < 0 && optind < argc;)
  595. XX                    {
  596. XX                        fid = ckfile (argv[optind], &size);
  597. XX                        if (fid < 0) optind++;
  598. XX                    }
  599.  
  600. XX                    strncpy (filename, argv[optind], sizeof filename);
  601.  
  602. XX                    if (block != 0)
  603. XX                    {
  604. XX                        size = -1;
  605. XX                    }
  606. XX                    recno = 0;
  607. XX                    stay = 0;
  608. XX                    status = lseek (fid, (long)0, 0);
  609. XX                }
  610. XX            }
  611. XX            ++recno;
  612. XX    /* ------------------------------------------------------------ */
  613. XX    /* if pause, beep and wait                                      */
  614. XX    /* ------------------------------------------------------------ */
  615. XX            if (status != EOF && pause)
  616. XX            {
  617. XX                pbrk = 0;
  618. XX                fprintf (stderr, "\007");
  619. XX                gets (response);
  620.  
  621. XX                if (pbrk) status = EOF;
  622. XX            }
  623.  
  624. XX            continue;
  625. XX        }
  626. XX    /* ------------------------------------------------------------ */
  627. XX    /* if we got here, this is an interactive session               */
  628. XX    /* ------------------------------------------------------------ */
  629. XX        stay = 0;
  630. XX        move (22, 0);
  631. XX    /* ------------------------------------------------------------ */
  632. XX    /* get the user's command                                       */
  633. XX    /* ------------------------------------------------------------ */
  634. XX        response[0] = EOF;
  635. XX        mvaddstr (22, 0, "> ");
  636. XX        clrtoeol ();
  637. XX        refresh ();
  638. XX        zp = getch ();
  639.  
  640. XX        if (debug && !dump)
  641. XX        {
  642. XX            if (isascii (zp) && isprint (zp))
  643. XX                errmsg ("command entered is %c", zp);
  644. XX            else errmsg ("command entered is ^%c (%#x)", zp + '@', zp);
  645. XX            getch ();
  646. XX        }
  647.  
  648. XX        if (isascii (zp) && isalpha (zp) && islower (zp))
  649. XX            zp = toupper (zp);
  650. XX    /* ------------------------------------------------------------ */
  651. XX    /* here we go - what does the user want?                        */
  652. XX    /* ------------------------------------------------------------ */
  653. XX        refresh ();
  654.  
  655. XX        switch (zp)
  656. XX        { 
  657. XX            case    '!':            /* shell escape                */
  658. XX                echo ();
  659. XX                move (23,0);
  660. XX                clrtoeol ();
  661. XX                addstr ("shell command: ");
  662. XX                refresh ();
  663. XX                getstr (response);
  664. XX                erase ();
  665. XX                refresh ();
  666. XX                nl ();
  667. XX                system (response);
  668. XX                noecho ();
  669. XX                nonl ();
  670. XX                move (23,0);
  671. XX                standout ();
  672. XX                addstr (" <Press any key> ");
  673. XX                standend ();
  674. XX                clrtoeol ();
  675. XX                refresh ();
  676. XX                getch ();
  677. XX                clear ();
  678. XX                break;
  679.  
  680. XX            case    '?':            /* HELP                        */
  681. XX                dbg_msg ("Help");
  682. XX                dohelp ();
  683. XX                touchwin (stdscr);
  684. XX                refresh ();
  685. XX                stay = 1;
  686. XX                break;
  687.  
  688. XX            case    '/':            /* search for a string        */
  689. XX                stay = 1;
  690. XX                if (mod)
  691. XX                {
  692. XX                    errmsg ("No write since last change");
  693. XX                }
  694. XX                else search (fid, zp);
  695. XX                break;
  696.  
  697. XX            case '-':                /* toggle options            */
  698. XX                zp = getch ();
  699. XX                stay = 1;
  700. XX                change = 0;
  701. XX                switch (zp)
  702. XX                {
  703. XX                    case 'a': /* ascii */
  704. XX                        if (ebcdic)
  705. XX                        {
  706. XX                            dbg_msg ("toggle to ascii");
  707. XX                            change = 1;
  708. XX                        }
  709. XX                        ebcdic = 0;
  710. XX                        break;
  711.  
  712. XX                    case 'e': /* ebcdic */
  713. XX                        if (ebcdic == 0)
  714. XX                        {
  715. XX                            dbg_msg ("toggle to ebcdic");
  716. XX                            change = 1;
  717. XX                        }
  718. XX                        ebcdic = 1;
  719. XX                        break;
  720.  
  721. XX                    case 's': /* swab */
  722. XX                        dbg_msg ("toggle byte swap");
  723. XX                        change = 1;
  724. XX                        schwapp (record, 256);
  725. XX                        swab = !swab;
  726. XX                        break;
  727. XX                }
  728. XX                if (change)
  729. XX                {
  730. XX                    show (bytes, record, filename, size,
  731. XX                            recno, position, m,reclen, dump,
  732. XX                            ebcdic, swab, block, honly);
  733. XX                }
  734.  
  735. XX                break;
  736.  
  737. XX            case '\022':            /* redraw screen (^R)        */
  738. XX                clear ();
  739. XX                show (bytes, record, filename, size, recno,
  740. XX                      position, m, reclen, dump, ebcdic,
  741. XX                      swab, block, honly);
  742. XX                stay = 1;
  743. XX                break;
  744. XX            
  745. XX            case    '\030':            /* toggle debug (^X)        */
  746. XX                debug = !debug;
  747. XX                break;
  748.  
  749. XX            case    '\006':            /* new file (^F)            */
  750. XX                close (fid);
  751. XX                fid = ckfile (cp = instr (), &size);
  752. XX                if (fid < 0)
  753. XX                {
  754. XX                    fid = ckfile (filename, &size);
  755. XX                }
  756. XX                else
  757. XX                {
  758. XX                    strncpy (filename, cp, sizeof filename);
  759. XX                    stay = 0;
  760. XX                    recno = 0;
  761. XX                }
  762. XX                break;
  763.  
  764. XX            case    '\016':            /* next file (^N)            */
  765. XX                if (mod)
  766. XX                {
  767. XX                    errmsg ("No write since last change");
  768. XX                    stay = 1;
  769. XX                }
  770. XX                else if (optind == (argc - 1))
  771. XX                {
  772. XX                    errmsg ("No more files");
  773. XX                    stay = 1;
  774. XX                }
  775. XX                else
  776. XX                {
  777. XX                    close (fid);
  778. XX                    for (fid = -1, optind++; fid < 0 && optind < argc;)
  779. XX                    {
  780. XX                        fid = ckfile (argv[optind], &size);
  781. XX                        if (fid < 0) optind++;
  782. XX                    }
  783. XX                    if (fid < 0)
  784. XX                    {
  785. XX                        errmsg ("could not handle the file list");
  786. XX                        reset (0);
  787. XX                    }
  788. XX                    strncpy (filename, argv[optind], sizeof filename);
  789. XX                    stay = 0;
  790. XX                    recno = 0;
  791. XX                }
  792. XX                break;
  793.  
  794. XX            case    '\020':            /* prev file (^P)            */
  795. XX                if (mod)
  796. XX                {
  797. XX                    errmsg ("No write since last change");
  798. XX                    stay = 1;
  799. XX                }
  800. XX                else if (optind == firstfile)
  801. XX                {
  802. XX                    errmsg ("No previous file");
  803. XX                    stay = 1;
  804. XX                }
  805. XX                else
  806. XX                {
  807. XX                    close (fid);
  808. XX                    for (fid = -1, optind--; fid < 0 && optind >= firstfile;)
  809. XX                    {
  810. XX                        fid = ckfile (argv[optind], &size);
  811. XX                        if (fid < 0) optind--;
  812. XX                    }
  813. XX                    if (fid < 0)
  814. XX                    {
  815. XX                        errmsg ("could not handle the file list");
  816. XX                        reset (0);
  817. XX                    }
  818. XX                    strncpy (filename, argv[optind], sizeof filename);
  819. XX                    stay = 0;
  820. XX                    recno = 0;
  821. XX                }
  822. XX                break;
  823.  
  824. XX            case    '\021':        /* quit absolutely (^Q)        */
  825. XX                status = EOF;
  826. XX                break;
  827.  
  828. XX            case DEL:            /* quit with check            */
  829. XX            case 'Q': /* quit */
  830. XX                if (mod)
  831. XX                {
  832. XX                    errmsg ("No write since last change!");
  833. XX                    stay = 1;
  834. XX                }
  835. XX                else
  836. XX                {
  837. XX                    status = EOF;
  838. XX                }
  839. XX                break;
  840.  
  841. XX            case '\\': /* back up 1 record */
  842. XX                if (mod)
  843. XX                {
  844. XX                    errmsg ("No write since last change");
  845. XX                    stay = 1;
  846. XX                }
  847. XX                else
  848. XX                {
  849. XX                    if (recno > 0)
  850. XX                    {
  851. XX                        --recno;
  852. XX                        stay = 0;
  853.  
  854. XX                        status = lseek (fid, (long)recno*256, 0);
  855. XX                        if (status < 0)
  856. XX                        {
  857. XX                            move (22, 0);
  858. XX                            clrtoeol ();
  859. XX                            perror (filename);
  860. XX                            errmsg ("error positioning in file");
  861. XX                            beep ();
  862. XX                            ++recno;
  863. XX                            stay = 1;
  864. XX                        }
  865. XX                    }
  866. XX                    else
  867. XX                    {
  868. XX                        errmsg ("No previous records");
  869. XX                        beep ();
  870. XX                        stay = 1;
  871. XX                    }
  872. XX                }
  873. XX                break; 
  874.  
  875. XX            case 'F': /* go to first record */
  876. XX                if (mod)
  877. XX                {
  878. XX                    errmsg ("No write since last change");
  879. XX                    stay = 1;
  880. XX                }
  881. XX                else
  882. XX                {
  883. XX                    status = lseek (fid, (long)0, 0);
  884. XX                    recno = 0;
  885. XX                }
  886. XX                break;
  887.  
  888. XX            case 'L': /* go to last record */
  889. XX                if (mod)
  890. XX                {
  891. XX                    errmsg ("No write since last change");
  892. XX                    stay = 1;
  893. XX                }
  894. XX                else
  895. XX                {
  896. XX                    position = lseek (fid, (long)0, 2);
  897. XX                    recno = position / 256;
  898. XX                    j = position % 256;
  899. XX                    if (j == 0) --recno;
  900. XX                    status = lseek (fid, (long)(recno*256), 0);
  901. XX                }
  902. XX                break;
  903.  
  904. XX            case 'U':            /* undo changes                    */
  905. XX                stay = 1;
  906. XX                mod = 0;
  907. XX                copyrec (unch_rec, record, sizeof record);
  908. XX                show (bytes, record, filename, size, recno,
  909. XX                        position, m,reclen, dump, ebcdic, swab,
  910. XX                        block, honly);
  911. XX                break;
  912.  
  913. XX            case 'R': /* re-read record */
  914. XX                status = lseek (fid, (long)recno*256, 0);
  915. XX                break;
  916.  
  917. XX            case '0': /* go to some address */
  918. XX            case '1':
  919. XX            case '2':
  920. XX            case '3':
  921. XX            case '4':
  922. XX            case '5':
  923. XX            case '6':
  924. XX            case '7':
  925. XX            case '8':
  926. XX            case '9':
  927. XX                if (mod)
  928. XX                {
  929. XX                    errmsg ("No write since last change");
  930. XX                    stay = 1;
  931. XX                }
  932. XX                else
  933. XX                {
  934. XX                    byteaddr = getnum (zp, FALSE);
  935. XX                    stay = 1;
  936. XX                    errmsg ("Position to byte %ld", byteaddr);
  937. XX                    if (!rawfile && byteaddr > size)
  938. XX                    {
  939. XX                        errmsg ("Address outside file");
  940. XX                        beep ();
  941. XX                    }
  942. XX                    else if (byteaddr / 256 != recno)
  943. XX                    {
  944. XX                        recno = byteaddr / 256;
  945. XX                        status = lseek (fid, (long)recno * 256, 0);
  946. XX                        stay = 0;
  947. XX                    }
  948. XX                }
  949. XX                break;
  950.  
  951. XX            case 'A': /* alpha modify */
  952. XX                stay = 1;
  953. XX                r = c = 0;
  954. XX                dbg_msg ("edit ascii");
  955. XX                if (bytes == 0) break;
  956. XX                touchwin (stdscr);
  957. XX                refresh ();
  958. XX                wmove (alphawin, r, c);
  959. XX                wrefresh (alphawin);
  960.  
  961. XX                while ((z = wgetch (alphawin)) != DEL)
  962. XX                {
  963. XX                    if (!arrow (z, &r, &c))
  964. XX                    {
  965. XX                        if (isascii (z))
  966. XX                        {
  967. XX                            if (isprint (z)) waddch (alphawin, z);
  968. XX                            else             waddch (alphawin, '.');
  969.  
  970. XX                            if (ebcdic) icc (&z, 1,"AE");
  971.  
  972. XX                            record[r][c] = z;
  973. XX                            mod = 1;
  974.  
  975. XX                            hexc = c * 3;
  976. XX                            wmove (hexwin, r, hexc);
  977. XX                            if (record[r][c] < '\0')
  978. XX                            {
  979. XX                                wprintw (hexwin, "%x%x",
  980. XX                                    (record[r][c] >> 4) & m,
  981. XX                                    record[r][c] & m);
  982. XX                            }
  983. XX                            else
  984. XX                            {
  985. XX                                wprintw (hexwin, "%02x", record[r][c]);
  986. XX                            }
  987. XX                            wrefresh (hexwin);
  988.  
  989. XX                        }
  990. XX                        else
  991. XX                        {
  992. XX                            beep ();
  993. XX                        }
  994.  
  995. XX                        if (c == 15)
  996. XX                        {
  997. XX                            if (r == 15) beep ();
  998. XX                            else
  999. XX                            {
  1000. XX                                c = 0;
  1001. XX                                ++r;
  1002. XX                            }
  1003. XX                        }
  1004. XX                        else
  1005. XX                        {
  1006. XX                            c++;
  1007. XX                        }
  1008. XX                    }
  1009. XX                    if (r * 16 + c >= bytes)
  1010. XX                    {
  1011. XX                        beep ();
  1012. XX                        r = (bytes - 1) / 16;
  1013. XX                        c = (bytes - 1) % 16;
  1014. XX                    }
  1015.  
  1016. XX                    wmove (alphawin, r, c);
  1017. XX                    wrefresh (alphawin);
  1018. XX                }
  1019.  
  1020. XX                break;
  1021.  
  1022. XX            case 'H': /* hex modify */
  1023. XX                dbg_msg ("edit hex");
  1024. XX                stay = 1;
  1025. XX                r = c = hexc = 0;
  1026. XX                if (bytes == 0) break;
  1027. XX                touchwin (stdscr);
  1028. XX                refresh ();
  1029. XX                wmove (hexwin, r, hexc);
  1030. XX                wrefresh (hexwin);
  1031.  
  1032. XX                while ((z = wgetch (hexwin)) != DEL)
  1033. XX                {
  1034. XX                    if (!arrow (z, &r, &c))
  1035. XX                    {
  1036. XX                        hexc = c * 3;
  1037. XX                        z = toupper (z);
  1038. XX                        if (!isxdigit (z))
  1039. XX                        {
  1040. XX                            beep ();
  1041. XX                        }
  1042. XX                        else
  1043. XX                        {
  1044. XX                            waddch (hexwin, tolower (z));
  1045. XX                            wrefresh (hexwin);
  1046.  
  1047. XX                            if (z > '9') z -= 7;
  1048.  
  1049. XX                            h = (z & m) << 4;
  1050.  
  1051. XX                            while (2)
  1052. XX                            {
  1053. XX                                z = EOF;
  1054. XX                                z = getch ();
  1055. XX                                if (z == EOF)
  1056. XX                                {
  1057. XX                                    pbrk = 0;
  1058. XX                                    h = -1;
  1059. XX                                    break;
  1060. XX                                }
  1061. XX                                z = toupper (z);
  1062. XX                                if (!isxdigit (z))
  1063. XX                                {
  1064. XX                                    beep ();
  1065. XX                                }
  1066. XX                                else
  1067. XX                                {
  1068. XX                                    waddch (hexwin, tolower (z));
  1069. XX                                    wrefresh (hexwin);
  1070. XX                                    if (z > '9') z -= 7;
  1071.  
  1072. XX                                    h |= z & m;
  1073. XX                                    break;
  1074. XX                                }
  1075. XX                            }
  1076.  
  1077. XX                            if (h < 0)
  1078. XX                            {
  1079. XX                                wmove (hexwin, r, hexc);
  1080. XX                                if (record[r][c] < '\0')
  1081. XX                                {
  1082. XX                                    wprintw (hexwin, "%x%x",
  1083. XX                                        (record[r][c] >> 4) & m,
  1084. XX                                        record[r][c] & m);
  1085. XX                                }
  1086. XX                                else
  1087. XX                                {
  1088. XX                                    wprintw (hexwin, "%02x", record[r][c]);
  1089. XX                                }
  1090. XX                                wrefresh (hexwin);
  1091. XX                                break;
  1092. XX                            }
  1093.  
  1094. XX                            record[r][c] = z = h;
  1095. XX                            mod = 1;
  1096.  
  1097. XX                            if (ebcdic) icc (&z, 1,"EA");
  1098.  
  1099. XX                            wmove (alphawin, r, c);
  1100. XX                            if (isascii (z) && isprint (z))
  1101. XX                                waddch (alphawin, z);
  1102. XX                            else waddch (alphawin, '.');
  1103. XX                            wrefresh (alphawin);
  1104.  
  1105. XX                            if (c == 15)
  1106. XX                            {
  1107. XX                                if (r == 15) beep ();
  1108. XX                                else
  1109. XX                                {
  1110. XX                                    c = 0;
  1111. XX                                    ++r;
  1112. XX                                }
  1113. XX                            }
  1114. XX                            else
  1115. XX                            {
  1116. XX                                c++;
  1117. XX                            }
  1118. XX                        }
  1119. XX                    }
  1120.  
  1121. XX                    if (r * 16 + c >= bytes)
  1122. XX                    {
  1123. XX                        beep ();
  1124. XX                        r = (bytes - 1) / 16;
  1125. XX                        c = (bytes - 1) % 16;
  1126. XX                    }
  1127.  
  1128. XX                    hexc = c * 3;
  1129. XX                    wmove (hexwin, r, hexc);
  1130. XX                    wrefresh (hexwin);
  1131. XX                }
  1132. XX                break;
  1133.  
  1134. XX            case 'W': /* write record */
  1135. XX                stay = 1;
  1136. XX                status = lseek (fid, position, 0);
  1137. XX                if (status != position)
  1138. XX                {
  1139. XX                    move (22, 0);
  1140. XX                    clrtoeol ();
  1141. XX                    perror (filename);
  1142. XX                    errmsg ("error positioning in file");
  1143. XX                    beep ();
  1144. XX                }
  1145. XX                if (swab) schwapp (record, 256);
  1146. XX                if (write (fid, record, bytes) != bytes)
  1147. XX                {
  1148. XX                    errmsg ("error writing to file");
  1149. XX                    sleep (1);
  1150. XX                    reset (0);
  1151. XX                    exit (0);
  1152. XX                }
  1153. XX                if (swab) schwapp (record, 256);
  1154. XX                mod = 0;
  1155. XX                errmsg ("Record written");
  1156. XX                break;
  1157.  
  1158. XX            case    '\n':        /* newline - next page            */
  1159. XX            case    '\r':
  1160. XX                if (mod)
  1161. XX                {
  1162. XX                    errmsg ("No write since last change");
  1163. XX                    stay = 1;
  1164. XX                }
  1165. XX                else
  1166. XX                {
  1167. XX                    ++recno;
  1168. XX                    if (!rawfile && (recno * 256) >= size)
  1169. XX                    {
  1170. XX                        recno--;
  1171. XX                        beep ();
  1172. XX                        errmsg ("No more records in file");
  1173. XX                        stay = 1;
  1174. XX                    }
  1175. XX                    else stay = 0;
  1176. XX                }
  1177. XX                break;
  1178.  
  1179. XX            default:
  1180. XX                if (isascii (zp) && isprint (zp))
  1181. XX                    errmsg ("Unknown command: %d", zp);
  1182. XX                else
  1183. XX                    errmsg ("Unknown command: %d", zp + '@');
  1184. XX                beep ();
  1185. XX                stay = 1;
  1186. XX                break;
  1187. XX        } /* end switch zp */
  1188. XX        refresh ();
  1189. XX    }
  1190.  
  1191. XX    if (windowed)
  1192. XX    {
  1193. XX        reset (0);
  1194. XX    }
  1195. XX    status = close (fid);
  1196.  
  1197. XX    exit (status);
  1198. XX}
  1199. XX/*S show - display a record on the terminal */
  1200. XX/*H show */
  1201. XX/*E*/
  1202. XXshow (bytes, record, filename, size, recno, position,
  1203. XX      m,reclen, dump, ebcdic, swab, block, honly)
  1204. XXint bytes;
  1205. XXint size;
  1206. XXint recno;
  1207. XXint position;
  1208. XXint m;
  1209. XXint reclen;
  1210. XXint dump;
  1211. XXint ebcdic;
  1212. XXint swab;
  1213. XXint honly;
  1214. XXchar record[16][16];
  1215. XXchar *filename;
  1216. XX{
  1217. XX    int        i;
  1218. XX    int        j;
  1219. XX    char    s;
  1220. XX    char    temp[16];
  1221. XX    char    *look = NULL;
  1222.  
  1223. XX    int        row = 0;
  1224. XX    int        col = 0;
  1225.  
  1226. XX    if (dump) printf ("\n\n");
  1227.  
  1228. XX    if (debug)
  1229. XX    {
  1230. XX        getyx (stdscr, row, col);
  1231. XX        move (23,0);
  1232. XX        printw ("show: %d|%d|%s|%d|%d|%d|%#x|%d|%d|%d|%d|%d|%d",
  1233. XX            bytes, record, filename, size, recno, position,
  1234. XX            m, reclen, dump, ebcdic, swab, block, honly);
  1235. XX        move (row, col);
  1236. XX        row = col = 0;
  1237. XX    }
  1238.  
  1239. XX    if (!dump) move (0, 0);
  1240. XX    outstr ("FILE: %s ", filename);
  1241. XX    if (block_spec) outstr ("(block special)");
  1242. XX    else if (char_spec) outstr ("(character special)");
  1243. XX    else if (fifo_spec) outstr ("(fifo (named pipe))");
  1244. XX    else if (dir_spec) outstr ("(directory - %ld)", size);
  1245. XX    else outstr ("(%ld)", size);
  1246.  
  1247. XX    if (ebcdic) outstr (" - EBCDIC");
  1248. XX    else outstr (" - ASCII");
  1249. XX    if (swab) outstr (" - SWAP");
  1250. XX    if (block) outstr (" - BLOCK (%d)", block);
  1251. XX    if (reclen) outstr (" - RECORD (%d)", reclen);
  1252.  
  1253. XX    if (!dump)
  1254. XX    {
  1255. XX        clrtoeol ();
  1256. XX        move (1,0);
  1257. XX        printw ("PAGE: %d (%d)", recno, position);
  1258. XX        clrtoeol ();
  1259. XX        row = 2;
  1260. XX    }
  1261. XX    else
  1262. XX    {
  1263. XX        printf ("\nPAGE: %d (%d)\n", recno, position);
  1264. XX    }
  1265.  
  1266. XX    if (honly)
  1267. XX    {
  1268. XX        look = (char *) record;
  1269. XX        for (j=0;j<256;++j)
  1270. XX        {
  1271. XX            if (*look++ != '\0')
  1272. XX            {
  1273. XX                look = NULL;
  1274. XX                break;
  1275. XX            }
  1276. XX        }
  1277. XX    }
  1278.  
  1279. XX    if (!dump) move (row, col);
  1280.  
  1281. XX    outstr ("    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf");
  1282. XX    outstr ("      0123456789abcdef");
  1283.  
  1284. XX    if (!dump)
  1285. XX    {
  1286. XX        row += 2;
  1287. XX        move (row, col);
  1288. XX    }
  1289. XX    else
  1290. XX    {
  1291. XX        printf ("\n\n");
  1292. XX    }
  1293. XX    for (i=0; i<=bytes/16; ++i)
  1294. XX    {
  1295. XX        if (honly && look != NULL)
  1296. XX        {
  1297. XX            i = 16;
  1298. XX            continue;
  1299. XX        }
  1300. XX        if (i*16+1 > bytes) continue;
  1301.  
  1302. XX        outstr ("%02x: ", i);
  1303.  
  1304. XX        for (j=0; j<16; ++j)
  1305. XX        {
  1306. XX            if (i*16+j < bytes)
  1307. XX            {
  1308. XX                if (record[i][j] < '\0')
  1309. XX                    outstr ("%x%x ",
  1310. XX                        (record[i][j] >> 4) & m, record[i][j] & m);
  1311. XX                else
  1312. XX                    outstr ("%02x ", record[i][j]);
  1313.  
  1314. XX                s = ' ';
  1315. XX                if (reclen > 0 && (position+i*16+j+1)%reclen == 0)
  1316. XX                    s = ':';
  1317. XX                if (block > 0 && (position+i*16+j+1)%block == 0)
  1318. XX                {
  1319. XX                    if (s == ' ')
  1320. XX                        s = '/';
  1321. XX                    else
  1322. XX                        s = '%';
  1323. XX                }
  1324. XX                if (s != ' ')
  1325. XX                    outstr ("\b%c", s);
  1326. XX            }
  1327. XX            else
  1328. XX            {
  1329. XX                outstr ("   ");
  1330. XX            }
  1331. XX        }
  1332.  
  1333. XX        outstr ("     ");
  1334.  
  1335. XX        copyrec (record[i], temp, 16);
  1336.  
  1337. XX        if (ebcdic) icc (temp, 16, "EA");
  1338.  
  1339. XX        for (j = 0; j < 16 && i*16+j < bytes; ++j)
  1340. XX        {
  1341. XX            if (temp[j] < ' ') outch ('.');
  1342. XX            else outstr ("%c", temp[j]);
  1343. XX        }
  1344.  
  1345. XX        if (!dump)
  1346. XX        {
  1347. XX            move (++row, col);
  1348. XX        }
  1349. XX        else
  1350. XX        {
  1351. XX            printf ("\n");
  1352. XX        }
  1353. XX    }
  1354.  
  1355. XX    if (!dump)
  1356. XX    {
  1357. XX        clrtobot ();
  1358. XX        refresh ();
  1359. XX    }
  1360.  
  1361. XX    return;
  1362. XX}
  1363. XX/*S breakp - set pbrk on interrupt */
  1364. XX/*H breakp */
  1365. XX/*E*/
  1366. XXint breakp (i)
  1367. XXint i;
  1368. XX{
  1369. XX    int s;
  1370. XX    extern int pbrk;
  1371. XX    s = (int) signal (SIGINT, breakp);
  1372. XX    pbrk = i;
  1373. XX}
  1374. XX/*S bread - buffered read */
  1375. XX/*H bread */
  1376. XX/*E*/
  1377. XXint bread (fid, record, want, block)
  1378. XXint fid, want, block;
  1379. XXchar *record;
  1380. XX{
  1381. XX    int i, j, k;
  1382. XX    int what, bytes, orig;
  1383. XX    static char buffer[10240];
  1384. XX    static int left, arrow;
  1385. XX    static int flag = 1;
  1386.  
  1387. XX    if (flag)
  1388. XX    {
  1389. XX        left = 0;
  1390. XX        arrow = 0;
  1391. XX        flag = 0;
  1392. XX    }
  1393.  
  1394. XX    if (block == 0)
  1395. XX        return (read (fid, record, want));
  1396.  
  1397. XX    if (block & 1) ++block;
  1398.  
  1399. XX    orig = what = want;
  1400. XX    while (1)
  1401. XX    {
  1402. XX        if (left < want)
  1403. XX        {
  1404. XX            if (left)
  1405. XX            {
  1406. XX                copyrec (&buffer[arrow], record, left);
  1407. XX                record += left;
  1408. XX                want -= left;
  1409. XX            }
  1410.  
  1411. XX            arrow = 0;
  1412. XX            left = 0;
  1413.  
  1414. XX            if ((bytes = read (fid, buffer, block)) < 0)
  1415. XX            {
  1416. XX                what = bytes;
  1417. XX                break;
  1418. XX            }
  1419.  
  1420. XX            if (bytes == 0)
  1421. XX            {
  1422. XX                what = orig - want;
  1423. XX                break;
  1424. XX            }
  1425.  
  1426. XX            left = bytes;
  1427. XX        }
  1428. XX        else
  1429. XX        {
  1430. XX            copyrec (&buffer[arrow], record, want);
  1431. XX            arrow += want;
  1432. XX            left -= want;
  1433. XX            break;
  1434. XX        }
  1435. XX    }
  1436.  
  1437. XX    return (what);
  1438. XX}
  1439. XX/*S schwapp - swap bytes in place */
  1440. XX/*H schwapp */
  1441. XX/*E*/
  1442. XXvoid
  1443. XXschwapp (ptr, nch)
  1444. XXregister char *ptr;
  1445. XXregister int nch;
  1446. XX{
  1447. XX    register int i;
  1448. XX    register char c;
  1449. XX    register char *ptra = ptr + 1;
  1450.  
  1451. XX    if (nch & 1) --nch;
  1452.  
  1453. XX    for (i = 0; i < nch; i += 2, ptr += 2, ptra += 2)
  1454. XX    {
  1455. XX        c = *ptr;
  1456. XX        *ptr = *ptra;
  1457. XX        *ptra = c;
  1458. XX    }
  1459. XX    return;
  1460. XX}
  1461. XX/*S copyrec - transfer bytes from f to t for nbytes bytes */
  1462. XX/*H copyrec */
  1463. XX/*E*/
  1464. XXvoid
  1465. XXcopyrec (f, t, nbytes)
  1466. XXregister char *f;
  1467. XXregister char *t;
  1468. XXregister int nbytes;
  1469. XX{
  1470. XX    register int i;
  1471.  
  1472. XX    for (i = 0; i < nbytes; i++, f++, t++) *t = *f;
  1473.  
  1474. XX    return;
  1475. XX}
  1476. XX/*S ebcdic codes corresponding to ascii - translation table */
  1477. XX/*Page Eject*/
  1478. XXchar ebcdic_codes[] = {
  1479. XX0, 0x1, 0x2, 0x3, 0x37, 0x2d, 0x2e, 0x2f, 0x16,
  1480. XX0x5, 0x25, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11,
  1481. XX0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f,
  1482. XX0x27, 0x1c, 0x1d, 0x1e, 0x1f, 0x40, 0x5a, 0x7f, 0x7b,
  1483. XX0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b,
  1484. XX0x60, 0x4b, 0x61, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
  1485. XX0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e,
  1486. XX0x6f, 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
  1487. XX0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
  1488. XX0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
  1489. XX0xe9, 0xad, 0xe0, 0xbd, 0x9a, 0x6d, 0x79, 0x81, 0x82,
  1490. XX0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92,
  1491. XX0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0xa2, 0xa3,
  1492. XX0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0,
  1493. XX0x5f, 0x7 };
  1494. XX/*S icc - internal code conversion */
  1495. XX/*H icc */
  1496. XX/*E*/
  1497. XXvoid
  1498. XXicc (buf, nch, type)
  1499. XXregister char *buf;
  1500. XXregister int nch;
  1501. XXchar *type;
  1502. XX{
  1503. XX    register int i;
  1504. XX    register int j;
  1505.  
  1506. XX    if (!strcmp (type, "AE"))
  1507. XX    {
  1508. XX        for (i = 0; i < nch; i++, buf++)
  1509. XX        {
  1510. XX            *buf = ebcdic_codes[*buf];
  1511. XX        }
  1512. XX    }
  1513. XX    else if (!strcmp (type, "EA"))
  1514. XX    {
  1515. XX        for (i = 0; i < nch; i++, buf++)
  1516. XX        {
  1517. XX            for (j = 0; j < 128; j++)
  1518. XX            {
  1519. XX                if (*buf == ebcdic_codes[j])
  1520. XX                {
  1521. XX                    *buf = j;
  1522. XX                    break;
  1523. XX                }
  1524. XX            }
  1525. XX        }
  1526. XX    }
  1527.  
  1528. XX    return;
  1529. XX}
  1530. XX/*S ckfile - check on existence, accessibility, and type of file */
  1531. XX/*H ckfile */
  1532. XX/*E*/
  1533. XXckfile (filename, sizep)
  1534. XXchar    *filename;
  1535. XXlong    *sizep;
  1536. XX{
  1537. XX    register int fid = 0;
  1538.  
  1539. XX    if (access (filename, 0) < 0)
  1540. XX    {
  1541. XX        errmsg ("file not found (%s)", filename);
  1542. XX        fid = -1;
  1543. XX    }
  1544.  
  1545. XX    if (block || pause || dump)
  1546. XX    {
  1547. XX        fid = open (filename, O_RDONLY, 0);
  1548. XX    }
  1549. XX    else
  1550. XX    {
  1551. XX        fid = open (filename, O_RDWR, 0);
  1552. XX    }
  1553.  
  1554. XX    if (fid < 0)
  1555. XX    {
  1556. XX        errmsg ("error opening file %s", filename);
  1557. XX        perror (filename);
  1558. XX        fid = -1;
  1559. XX    }
  1560. XX    else
  1561. XX    {
  1562. XX        errmsg ("File %s opened successfully ", filename);
  1563. XX        if (fstat (fid, &sb) == -1)
  1564. XX        {
  1565. XX            fprintf (stderr, "Can't stat\n");
  1566. XX            perror (filename);
  1567. XX            fid = -1;
  1568. XX        }
  1569. XX        else
  1570. XX        {
  1571. XX            block_spec = (sb.st_mode & S_IFMT) == S_IFBLK;
  1572. XX            char_spec = (sb.st_mode & S_IFMT) == S_IFCHR;
  1573. XX            fifo_spec = (sb.st_mode & S_IFMT) == S_IFIFO;
  1574. XX            dir_spec = (sb.st_mode & S_IFMT) == S_IFDIR;
  1575. XX            rawfile = block_spec || char_spec || fifo_spec;
  1576.  
  1577. XX            if (rawfile) *sizep = -1;
  1578. XX            else
  1579. XX            {
  1580. XX                if (sb.st_size == 0)
  1581. XX                {
  1582. XX                    fprintf (stderr,
  1583. XX                        "file %s is empty (zero bytes)\n",
  1584. XX                        filename);
  1585. XX                    fid = -1;
  1586. XX                }
  1587. XX                *sizep = sb.st_size;
  1588. XX            }
  1589. XX        }
  1590. XX    }
  1591.  
  1592. XX    return fid;
  1593. XX}
  1594. XX/*S dohelp - display help text */
  1595. XX/*H dohelp */
  1596. XX/*E*/
  1597. XXdohelp ()
  1598. XX{
  1599. XX    static char *helptxt[] = {
  1600. XX    "!   - execute command in the shell",    "a   - edit ascii portion",
  1601. XX    "-x   - toggle command line option",    "f   - display first page of file",
  1602. XX    "<cr> - display next page",    NULL,
  1603. XX    "?    - display this help text",    "h   - edit hexadecimal portion",
  1604. XX    "DEL  - quit the program",        "l   - display last page of file",
  1605. XX    "\\    - display previous page",        "nnn - direct addressing",
  1606. XX    "/    - search for ASCII string",        "q   - quit the program",
  1607. XX    "^f   - select named file",        "r   - reread the current page",
  1608. XX    "^n   - select next file",        "u   - undo all changes to page",
  1609. XX    "^p   - select previous file",        "w   - write out changed page",
  1610. XX    "^q   - quit without writing changes",    NULL,
  1611. XX    "^r   - redraw the screen",    NULL,
  1612. XX    "^x   - turn on debug",    NULL,
  1613. XX    "----------------------------------------------------------------", NULL,
  1614. XX    "direct addressing: nnnS, where nnn = some number, and", NULL,
  1615. XX    "                      S = type suffix", "b = block (512)",
  1616. XX    NULL, "k = kilobyte (1024)",
  1617. XX    NULL, "l = long word (4)",
  1618. XX    NULL, "p = page (256)",
  1619. XX    NULL, "w = word (2)",
  1620. XX    NULL, "<cr> = byte",
  1621. XX    };
  1622.  
  1623. XX    static int nmsg = sizeof helptxt / sizeof (char *);
  1624. XX    register int row = 0;
  1625. XX    register int i;
  1626.  
  1627. XX    register WINDOW *helpwin;
  1628. XX    extern WINDOW *newwin ();
  1629.  
  1630. XX    helpwin = newwin (LINES, COLS, 0, 0);
  1631. XX    werase (helpwin);
  1632. XX    wrefresh (helpwin);
  1633.  
  1634. XX    wmove (helpwin, 0, 1);
  1635. XX    waddstr (helpwin,
  1636. XX"---------------------------------- HELP ----------------------------------");
  1637.  
  1638. XX    for (row = 1, i = 0; i < nmsg; i+=2)
  1639. XX    {
  1640. XX        if (helptxt[i])
  1641. XX        {
  1642. XX            wmove (helpwin, row, 1);
  1643. XX            waddstr (helpwin, helptxt[i]);
  1644. XX        }
  1645. XX        if (i+1 <= nmsg && helptxt[i+1])
  1646. XX        {
  1647. XX            wmove (helpwin, row, 41);
  1648. XX            waddstr (helpwin, helptxt[i+1]);
  1649. XX        }
  1650. XX        row++;
  1651. XX    }
  1652.  
  1653. XX    wmove (helpwin, 23, 0);
  1654. XX    wstandout (helpwin);
  1655. XX    waddstr (helpwin, " <Press any key> ");
  1656. XX    wstandend (helpwin);
  1657. XX    wclrtoeol (helpwin);
  1658. XX    wrefresh (helpwin);
  1659. XX    wgetch (helpwin);
  1660. XX    werase (helpwin);
  1661. XX    wrefresh (helpwin);
  1662. XX    delwin (helpwin);
  1663.  
  1664. XX    return;
  1665. XX}
  1666. XX/*S reset - reset terminal to original state */
  1667. XX/*H reset */
  1668. XX/*E*/
  1669. XXreset (sig)
  1670. XXint sig;
  1671. XX{
  1672. XX    move (23, 0);
  1673. XX    refresh ();
  1674. XX    endwin ();
  1675. XX    if (sig) fprintf (stderr, "killed with signal %d\n", sig);
  1676. XX    exit (sig);
  1677. XX}
  1678. XX/*S arrow - determine if current character is a cursor control key */
  1679. XX/*H arrow */
  1680. XX/*E*/
  1681. XXarrow (k, r, c, type)
  1682. XXregister int k;
  1683. XXregister int *r;
  1684. XXregister int *c;
  1685. XXregister int type;
  1686. XX{
  1687. XX    register ret = 1;
  1688.  
  1689. XX    if (k == KEY_UP)
  1690. XX    {
  1691. XX        if (*r == 0) beep ();
  1692. XX        else (*r)--;
  1693. XX    }
  1694. XX    else if (k == KEY_DOWN || k == '\n')
  1695. XX    {
  1696. XX        if (*r == 15) beep ();
  1697. XX        else (*r)++;
  1698. XX    }
  1699. XX    else if (k == KEY_LEFT || k == '\b' )
  1700. XX    {
  1701. XX        if (*c == 0)
  1702. XX        {
  1703. XX            if (*r == 0) beep ();
  1704. XX            else
  1705. XX            {
  1706. XX                *c = 15;
  1707. XX                (*r)--;
  1708. XX            }
  1709. XX        }
  1710. XX        else (*c)--;
  1711. XX    }
  1712. XX    else if (k == KEY_RIGHT)
  1713. XX    {
  1714. XX        if (*c == 15)
  1715. XX        {
  1716. XX            if (*r == 15) beep ();
  1717. XX            else
  1718. XX            {
  1719. XX                *c = 0;
  1720. XX                (*r)++;
  1721. XX            }
  1722. XX        }
  1723. XX        else (*c)++;
  1724. XX    }
  1725. XX    else if (k == KEY_HOME)
  1726. XX    {
  1727. XX        *r = *c = 0;
  1728. XX    }
  1729. XX    else
  1730. XX    {
  1731. XX        ret = 0;
  1732. XX    }
  1733.  
  1734. XX    return ret;
  1735. XX}
  1736. XX/*S dbg_msg - print a debug message */
  1737. XX/*H dbg_msg */
  1738. XX/*E*/
  1739. XXdbg_msg (msg)
  1740. XXregister char *msg;
  1741. XX{
  1742. XX    if (debug && !dump)
  1743. XX    {
  1744. XX        errmsg (msg);
  1745. XX    }
  1746.  
  1747. XX    return;
  1748. XX}
  1749. XX/*S instr - get a character string from the terminal */
  1750. XX/*H instr */
  1751. XX/*E*/
  1752. XXchar *
  1753. XXinstr ()
  1754. XX{
  1755. XX    static char buf[512];
  1756.  
  1757. XX    register int c;
  1758. XX    register char *p = buf;
  1759. XX    register int col = 0;
  1760.  
  1761. XX    move (22, 0);
  1762. XX    clrtoeol ();
  1763. XX    refresh ();
  1764.  
  1765. XX    while ((c = getch ()) != '\r')
  1766. XX    {
  1767. XX        if (isascii (c) && isprint (c))
  1768. XX        {
  1769. XX            move (22, col);
  1770. XX            addch (c);
  1771. XX            *p++ = c;
  1772. XX            col++;
  1773. XX        }
  1774. XX        else if (c == '\b')
  1775. XX        {
  1776. XX            p--;
  1777. XX            col--;
  1778. XX            move (22, col);
  1779. XX            addch (' ');
  1780. XX            move (22, col);
  1781. XX        }
  1782. XX        refresh ();
  1783. XX    }
  1784.  
  1785. XX    refresh ();
  1786.  
  1787. XX    *p = '\0';
  1788.  
  1789. XX    return buf;
  1790. XX}
  1791. XX/*S getnum - retrieve a number from the terminal */
  1792. XX/*H getnum */
  1793. XX/*E*/
  1794. XXlong
  1795. XXgetnum (frst_char, hex)
  1796. XXregister int frst_char;
  1797. XXregister int hex;
  1798. XX{
  1799. XX    static char buf[64];
  1800.  
  1801. XX    register int c;
  1802. XX    register char *p = buf;
  1803. XX    register int col = 0;
  1804.  
  1805. XX    register long retval = 0;
  1806.  
  1807. XX    move (22, 0);
  1808. XX    clrtoeol ();
  1809. XX    if (frst_char)
  1810. XX    {
  1811. XX        addch (frst_char);
  1812. XX        *p++ = frst_char;
  1813. XX        col++;
  1814. XX        refresh ();
  1815. XX    }
  1816.  
  1817. XX    while ((c = getch()) != '\r')
  1818. XX    {
  1819. XX        if (isascii (c))
  1820. XX        {
  1821. XX            if ((hex && isxdigit (c)) || isdigit (c))
  1822. XX            {
  1823. XX                move (22, col);
  1824. XX                addch (c);
  1825. XX                *p++ = c;
  1826. XX                col++;
  1827. XX            }
  1828. XX            else if (c == '\b')
  1829. XX            {
  1830. XX                p--;
  1831. XX                col--;
  1832. XX                move (22, col);
  1833. XX                addch (' ');
  1834. XX                move (22, col);
  1835. XX            }
  1836. XX            else
  1837. XX            {
  1838. XX                break;            /* some character typing the value    */
  1839. XX            }
  1840. XX            refresh ();
  1841. XX        }
  1842. XX    }
  1843.  
  1844. XX    *p = '\0';
  1845.  
  1846. XX    retval = atol (buf);
  1847.  
  1848. XX    mvprintw (22, 0, "%ld", retval);
  1849. XX    switch (c)
  1850. XX    {
  1851. XX        case    'b':            /* block - 512 bytes                */
  1852. XX            retval *= 512;
  1853. XX            break;
  1854. XX        case    'k':            /* 1024 bytes                        */
  1855. XX            retval *= 1024;
  1856. XX            break;
  1857. XX        case    'l':            /* long word - 4 bytes                */
  1858. XX            retval *= 4;
  1859. XX            break;
  1860. XX        case    'p':            /* page - 256 bytes                    */
  1861. XX            retval *= 256;
  1862. XX            break;
  1863. XX        case    'w':            /* word - 2 bytes                    */
  1864. XX            retval *= 2;
  1865. XX            break;
  1866. XX        case    '\r':            /* just clear it for display        */
  1867. XX            c = '\0';
  1868. XX            break;
  1869. XX    }
  1870.  
  1871. XX    printw ("%c -> %ld byte offset", c, retval);
  1872. XX    clrtoeol ();
  1873.  
  1874. XX    refresh ();
  1875.  
  1876. XX    return retval;
  1877. XX}
  1878. XX/*S search - look for an ascii string in the file */
  1879. XX/*H search */
  1880. XX/*E*/
  1881. XXsearch (fid)
  1882. XXregister int fid;
  1883. XX{
  1884. XX    long    curpos = position;
  1885. XX    long    currec = recno;
  1886.  
  1887. XX    char    lrecord[sizeof record + 1];
  1888.  
  1889. XX    register int i;
  1890. XX    register int matched = 0;
  1891. XX    register int srch_len;
  1892.  
  1893. XX    register char *cp = instr ();
  1894. XX    register char *rp;
  1895.  
  1896. XX    int row, col;
  1897.  
  1898. XX    srch_len = strlen (cp);
  1899. XX    copyrec (record, lrecord, sizeof record);
  1900. XX    lrecord[256] = '\0';
  1901.  
  1902. XX    pbrk = 0;
  1903.  
  1904. XX    wmove (errwin, 0, 0);
  1905. XX    wstandout (errwin);
  1906. XX    wmove (errwin, 0, 40);
  1907. XX    wstandend (errwin);
  1908. XX    wmove (errwin, 0, 1);
  1909. XX    waddstr (errwin, "..searching record ");
  1910. XX    getyx (errwin, row, col);
  1911.  
  1912. XX    do
  1913. XX    {
  1914. XX        mvwprintw (errwin, row, col, "%ld", currec);
  1915. XX        wrefresh (errwin);
  1916.  
  1917. XX        for (i = 0, rp = lrecord, matched = 0;
  1918. XX             !matched && i < 256;
  1919. XX             rp++, i++)
  1920. XX        {
  1921. XX            if (*cp == *rp && !strncmp (cp, rp, srch_len))
  1922. XX            {
  1923. XX                matched = 1;
  1924. XX                break;
  1925. XX            }
  1926. XX        }
  1927.  
  1928. XX        if (!matched)
  1929. XX        {
  1930. XX            bytes = bread (fid, lrecord, 256, block);
  1931. XX            currec++;
  1932. XX            lrecord[256] = '\0';
  1933. XX        }
  1934. XX    }    while (!pbrk && bytes && !matched);
  1935.  
  1936. XX    if (matched)
  1937. XX    {
  1938. XX        recno = currec;
  1939. XX        stay = 0;
  1940. XX        copyrec (record, unch_rec, sizeof record);
  1941. XX        werase (errwin);
  1942. XX        wrefresh (errwin);
  1943. XX    }
  1944. XX    else
  1945. XX    {
  1946. XX        errmsg ("String %s not found", cp);
  1947. XX        stay = 1;
  1948. XX    }
  1949.  
  1950. XX    return;
  1951. XX}
  1952. XXerrmsg (fmt, arg1, arg2, arg3, arg4)
  1953. XXregister char *fmt;
  1954. XXregister char *arg1;
  1955. XXregister char *arg2;
  1956. XXregister char *arg3;
  1957. XXregister char *arg4;
  1958. XX{
  1959. XX    int y, x;
  1960.  
  1961. XX    if (!dump)
  1962. XX    {
  1963. XX        getyx (stdscr, y, x);
  1964. XX        wmove (errwin, 0, 0);
  1965. XX        wstandout (errwin);
  1966. XX        wprintw (errwin, fmt, arg1, arg2, arg3, arg4);
  1967. XX        wstandend (errwin);
  1968. XX        wclrtoeol (errwin);
  1969. XX        wrefresh (errwin);
  1970. XX        move (y, x);
  1971. XX    }
  1972. XX    else
  1973. XX    {
  1974. XX        fprintf (stderr, fmt, arg1, arg2, arg3, arg4);
  1975. XX    }
  1976. XX    return;
  1977. XX}
  1978. XXoutstr (fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
  1979. XXregister char *fmt;
  1980. XXregister char *arg1;
  1981. XXregister char *arg2;
  1982. XXregister char *arg3;
  1983. XXregister char *arg4;
  1984. XXregister char *arg5;
  1985. XXregister char *arg6;
  1986. XXregister char *arg7;
  1987. XX{
  1988. XX    if (dump) printf (fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  1989. XX    else printw (fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  1990.  
  1991. XX    return;
  1992. XX}
  1993. XXoutch (ch)
  1994. XXregister char ch;
  1995. XX{
  1996. XX    if (dump) putchar (ch);
  1997. XX    else addch (ch);
  1998.  
  1999. XX    return;
  2000. XX}
  2001. @//E*O*F bpatch.c//
  2002. chmod u=rw,g=rw,o=rw $OUT
  2003.  
  2004. echo Inspecting for damage in transit...
  2005. temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
  2006. trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
  2007. cat > $temp <<\!!!
  2008.       28     259    1521 README
  2009.       20      83     485 Makefile
  2010.      138     990    5412 bpatch.1
  2011.     1749    5447   35893 bpatch.c
  2012.     1935    6779   43311 total
  2013. !!!
  2014. wc  README Makefile bpatch.1 bpatch.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
  2015. if test -s $dtemp ; then
  2016.     echo "Ouch [diff of wc output]:"
  2017.     cat $dtemp
  2018.     STATUS=1
  2019. elif test $STATUS = 0 ; then
  2020.     echo "No problems found."
  2021. else
  2022.     echo "WARNING -- PROBLEMS WERE FOUND..."
  2023. fi
  2024. exit $STATUS
  2025.